const Usecase = require('../../shared/usecase/Usecase')
const User = require('../../domain/user/user')
const {
  UsernameExistError,
  PhoneExistError,
  EmailExistError,
} = require('../../domain/user/error')
const R = require('ramda')

class CreateUser extends Usecase {
  constructor({ userRepo, database, logger }) {
    super(['UserCreated'], logger)
    this.userRepo = userRepo
    this.sequelize = database.sequelize
  }

  async _validate(data) {
    await data.validate()
    let user
    user = await this.userRepo.findByUsername(data.username)
    if (user) throw new UsernameExistError()
    if (data.phone) {
      user = await this.userRepo.findByPhone(data.phone)
      if (user) throw new PhoneExistError()
    }
    if (data.email) {
      user = await this.userRepo.findByPhone(data.email)
      if (user) throw new EmailExistError()
    }
  }

  async execute(data, currentUser) {
    const { UserCreated } = this.eventMap
    const userEntity = User.create(data)
    // 业务检查
    await this._validate(userEntity)
    const transaction = await this.sequelize.transaction()
    try {
      await userEntity.bcryptPassword()
      if (data.roleIdList && data.roleIdList) {
        userEntity.updateRoleList(data.roleIdList)
      }
      await this.userRepo.createAndSetRoleList(userEntity, {
        currentUser,
        transaction,
      })
      this.emit(UserCreated, R.omit(['password', 'salt'], userEntity))
      await transaction.commit()
      return userEntity
    } catch (error) {
      await transaction.rollback()
      throw error
    }
  }
}

module.exports = CreateUser
